﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GcmpModuleGroup.h"
#include "IObject.h"

namespace gcmp
{
    using ModuleGroupUid = std::pair<Guid, std::wstring>;

    /// \brief 专业管理器
    ///
    /// 全局唯一，用以设置、获取.dll所属专业、建立专业依赖关系、检测专业依赖合法性
    /// 需要在程序开始调用以下接口进行初始化设置：
    /// 1. 调用AddModuleGroups接口来添加所有专业
    /// 2. 再调用SetDirectPreModuleGroups接口设置以上已经添加的专业之间的依赖关系
    /// 专业以ModuleGroupUid表示，其中Guid为专业唯一标识，wstring为专业名称
    /// 默认已添加一个{Guid::Invalid, L"GcmpInternal"}专业
    class GCMP_MODULEGROUP_EXPORT IModuleGroupManager : public IObject
    {
        DEFINE_CAST_DERIVED(gcmp::IModuleGroupManager, gcmp::IObject);

    public:
        /// \brief 全局专业管理器单例获取
        /// \return IModuleGroupManager* 获取的全局专业管理器单例
        static IModuleGroupManager * Get();

        /// \brief 添加专业
        /// \param moduleGroups 添加的专业Guid及名称信息
        /// \return bool 是否添加成功
        virtual bool AddModuleGroups(const std::vector<ModuleGroupUid> & moduleGroups) = 0;

        /// \brief 根据专业Guid获得专业名称，如不存在返回空
        /// \param moduleGroupGuid 该专业Guid
        /// \return bool 是否设置成功
        virtual const std::wstring& GetModuleGroupName(const Guid & moduleGroupGuid) const = 0;

        /// \brief 设置某专业的直接前置专业
        /// \param moduleGroupGuid 该专业Guid
        /// \param preSpecialitiesGuid 该专业的直接前置专业Guid
        /// \return bool 是否设置成功
        virtual bool SetDirectPreModuleGroups(const Guid & moduleGroupGuid, const std::set<Guid, GuidComparer>& preSpecialitiesGuids) = 0;

        /// \brief 获取某个专业的直接前置专业
        /// \param moduleGroupGuid 该专业Guid
        /// \param preSpecialitiesGuids 获取的该专业的直接前置专业Guid
        /// \return bool 是否获取成功
        virtual bool GetDirectPreModuleGroups(const Guid & moduleGroupGuid, std::set<Guid, GuidComparer>& preSpecialitiesGuids) const = 0;

        /// \brief 获取某个专业的所有前置专业
        /// \param moduleGroupGuid 该专业Guid
        /// \param preSpecialitiesGuids 获取的该专业的所有前置专业Guid
        /// \return bool 是否获取成功
        virtual bool GetAllPreModuleGroups(const Guid & moduleGroupGuid, std::set<Guid, GuidComparer>& preSpecialitiesGuids) const = 0;

        /// \brief 设置.dll所属专业，不允许设置dll属于多个专业
        /// \param dllName 需设置的.dll的名称
        /// \param moduleGroupGuid 该.dll所属的专业Guid
        /// \return bool 是否设置成功
        virtual bool SetModuleGroupOfDll(const std::wstring & dllName, const Guid & moduleGroupGuid) = 0;

        /// \brief 获取.dll所属专业，如果没有记录返回Invalid
        /// \param dllName 该dll的名称
        /// \return Guid 获取的.dll所属专业
        virtual Guid GetModuleGroupOfDll(const std::wstring & dllName) const = 0;

        /// \brief 获取某个专业的所有.dll
        /// \param moduleGroupGuid 专业Guid
        /// \return std::set<wstring> 获取的某个专业的所有.dll名称
        virtual std::set<std::wstring> GetAllDllsOfModuleGroup(const Guid& moduleGroupGuid) const = 0;

        /// \brief 检测合法性
        ///
        /// 专业的依赖不能成环
        /// \param pErrorMessage 错误信息，返回值为false时有效
        /// \return bool 是否检测成功。不成功时，错误消息通过pErrorMessage传出
        virtual bool Validate(std::wstring * pErrorMessage) const = 0;

        /// \brief 打印所有专业、它们的依赖关系、专业加载过的dll/addin
        /// \return std::wstring 打印信息
        virtual std::wstring Dump() const = 0;
    };
}
